package marshal

import (
	"bytes"
	"encoding/binary"
	"errors"
)

const (
	FirstLen_1 = 1 << iota
	FirstLen_2
	FirstLen_4
)

var (
	ERROR_DECODE_LEN_NOT_ENOUGH = errors.New("ERROR_DECODE_LEN_NOT_ENOUGH")
)

type IEncodeDecode interface {
	Encode(data []byte) ([]byte, error)
	Decode(data []byte) ([]byte, int, error)
}

type IEncode interface {
	Encode(data []byte) ([]byte, error)
}

// 解码单个包如果不全，则需要放弃解码，error返回ERROR_DECODE_LEN_NOT_ENOUGH
type IDecode interface {
	//解码
	//@return []byte 解析出来的字节
	//@return int 解析的长度
	//@return error 解码错误
	Decode(data []byte) ([]byte, int, error)
}

// 可变长度解码器
type VariableDecode struct {
	FirstRecevedLen int //首部长度字节数支持1, 2, 4字节
}

type VariableEncode struct {
	FirstSendLen int //首部长度字节数支持1, 2, 4字节
}

func (v *VariableEncode) Encode(data []byte) ([]byte, error) {
	var buf bytes.Buffer

	switch v.FirstSendLen {
	case FirstLen_1:
		buf.WriteByte(data[0])
	case FirstLen_2:
		bs2 := make([]byte, 2)
		binary.BigEndian.PutUint16(bs2, uint16(len(data)))
		buf.Write(bs2)
	case FirstLen_4:
		bs4 := make([]byte, 4)
		binary.BigEndian.PutUint32(bs4, uint32(len(data)))
		buf.Write(bs4)
	}
	buf.Write(data)
	return buf.Bytes(), nil
}

func (v *VariableDecode) Decode(data []byte) ([]byte, int, error) {
	if len(data) < v.FirstRecevedLen {
		return nil, 0, ERROR_DECODE_LEN_NOT_ENOUGH
	}
	bs := data[0:v.FirstRecevedLen]
	var bslen int
	switch v.FirstRecevedLen {
	case FirstLen_1:
		bslen = int(bs[0])
	case FirstLen_2:
		bslen = int(binary.BigEndian.Uint16(bs))
	case FirstLen_4:
		bslen = int(binary.BigEndian.Uint32(bs))
	}
	if len(data)-v.FirstRecevedLen >= bslen {
		return data[v.FirstRecevedLen : v.FirstRecevedLen+bslen], bslen + v.FirstRecevedLen, nil
	}
	return nil, 0, ERROR_DECODE_LEN_NOT_ENOUGH
}
